﻿using System;
using System.Collections.Generic;
using System.Linq;
using Shinkansen.Core;
using Shinkansen.Model;
using Shinkansen.Runtime;
using Shinkansen.UI;

namespace Shinkansen.Web.UI.WebControls
{
    public class CssTagBuilder : TagBuilderBase
    {
        private readonly ShinkansenOptions _options;
        private readonly IEnumerable<CssInclude> _cssIncludes;
        private readonly Action<string> _registrationCallback;

        /// <summary>
        /// Initializes a new instance of the <see cref="CssTagBuilder"/> class.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="cssIncludes">The CSS includes.</param>
        /// <param name="registrationCallback">The tag registrar.</param>
        public CssTagBuilder (ShinkansenOptions options, IEnumerable<CssInclude> cssIncludes, Action<string> registrationCallback)
        {
            _options = options;
            _cssIncludes = cssIncludes;
            _registrationCallback = registrationCallback;
        }

        /// <summary>
        /// Processes CSS includes.
        /// </summary>
        public override void Run ()
        {
            if (!_cssIncludes.Any ())
                return;

            Action actor = _options.Combine
               ? (Action)(CombineAllCss)
               : RegisterIndividualCssResources;

            actor ();
        }


        /// <summary>
        /// Combines all CSS.
        /// </summary>
        private void CombineAllCss ()
        {
            IEnumerable<IStaticInclude> css = _cssIncludes.Cast<IStaticInclude> ();

            IQueryStringBuilder builder = 
                new QueryStringForCssBuilder (
                    new QueryStringWithCompressionBuilder (
                        new QueryStringWithCrunchingBuilder (
                            new CombinedQueryStringBuilder (css), _options.Crunch), _options.HttpCompressWith));

            EncryptedQueryString qs = new EncryptedQueryString ();
            builder.ConstructQueryString (qs);

            string tag = BuildLinkTag (qs);
            _registrationCallback (tag);
        }


        /// <summary>
        /// Registers the individual CSS resources.
        /// </summary>
        private void RegisterIndividualCssResources ()
        {
            foreach (CssInclude css in _cssIncludes)
            {
                IQueryStringBuilder builder = 
                    new QueryStringForCssBuilder (
                        new QueryStringWithCompressionBuilder (
                            new QueryStringWithCrunchingBuilder (
                                new IndividualQueryStringBuilder (css), _options.Crunch), _options.HttpCompressWith));

                EncryptedQueryString qs = new EncryptedQueryString ();
                builder.ConstructQueryString (qs);

                string tag = BuildLinkTag (qs);
                _registrationCallback (tag);
            }
        }

        /// <summary>
        /// Builds the link tag.
        /// </summary>
        /// <param name="qs">The qs.</param>
        /// <returns></returns>
        private string BuildLinkTag (QueryString qs)
        {
            return string.Format ("<link rel='stylesheet' type='text/css' href='{0}?{1}={2}' />", PathToAxd, Tokens.SecureToken, qs);
        }
    }
}
